<?php

class inkModel extends Model
{
  protected $_sql = null;

  public function sql($info, $mode = null, $begin = null) {
    if($begin) $this->$_sql = null;
    if($mode === 'search') {
      $sql = array('select * from '.$this->_tableName);
      if(isset($info['all'])) {
        if($info['catid']) $this->catidToModelid($modelid, $info['catid']);
        if($info['modelid']) $this->addModelid($modelid, $info['modelid']);
        if($modelid) array_push($sql, $this->modelidToLeftJoin($modelid));
      }
      array_push($sql, 'where 1=1');
      if($info['catid']) array_push($sql, $this->whereCatid($info['catid']));
      if($info['modelid']) array_push($sql, $this->whereModelid($info['modelid']));
      if($info['text']) {
        if($info['name']) {
          array_push($sql, $this->whereType($info['text'], $info['name']));
        } else {
          array_push($sql, $this->whereType($info['text']));
        }
      }
      $data = $this->query(implode(' ', $sql)." order by listorder desc, time desc ".$this->_parts['limit'].";")->fetchAll(PDO::FETCH_ASSOC);
      $data = array_map(function($value) {
        $value['url'] = '/index.php?id='.$value['id'];
        return $value;
      }, $data);
      return $data;
    }
    return $this;
  }

  protected function catidToModelid(&$modelid, $id) {
    $id = $this->query("select modelid from ".$this->_prefix."category where catid in ('".str_replace(",", "','", $id)."');")->fetchAll(PDO::FETCH_ASSOC);
    foreach($id as $value) $temp .= ','.$value['modelid'];
    $modelid = ltrim($modelid.$temp, ',');
    $this->orderId($modelid);
  }

  protected function addModelid(&$modelid, $id) {
    $modelid = ltrim($modelid.','.$id, ',');
    $this->orderId($modelid);
  }

  protected function orderId(&$id) {
    $id = str_replace(',,', ',', $id);
    $id = explode(',', $id);
    sort($id);
    $id = array_unique($id);
    $id = implode(',', $id);
  }

  protected function modelidToLeftJoin($id, $join = 'id') {
    $table = $this->query("select tablename from ".$this->_prefix."model where modelid in ('".str_replace(",", "','", $id)."');")->fetchAll(PDO::FETCH_ASSOC);
    foreach($table as $value) $sql .= 'left join '.$this->_prefix.$value['tablename'].' using('.$join.') ';
    return trim($sql);
  }

  protected function whereCatid($id) {
    $this->orderId($id);
    return "and ".$this->_tableName.".catid in (".$id.")";
  }

  protected function whereModelid($id) {
    $this->orderId($id);
    return "and ".$this->_tableName.".modelid in (".$id.")";
  }

  protected function whereType($text, $name = 'title') {
    $names = explode(',', $name);
    // id catid modelid title thumb keywords description listorder status hits username time
    $normal = $this->getTableColumn($this->_tableName);
    $sql = array();
    foreach($names as $value) {
      if(in_array($value, $normal, true)) {
        array_push($sql, $this->whereTypeSQL($value, $text));
      } else {
        $formtype = $this->fieldToFormtype($value);
        array_push($sql, $this->whereTypeSQL($value, $text, $formtype));
      }
    }
    $sql = array_filter($sql);
    return "and (".implode(" or ", $sql).")";
  }

  protected function whereTypeSQL($find, $text, $type = null) {
    // input textarea editor radio checkbox file files

    if($type === null && in_array($find, array('title', 'thumb', 'keywords', 'description'), true) || in_array($type, array('input', 'textarea', 'file', 'files'), true)) return "`".$find."` like '%".str_replace(",", "%' or `".$find."` like '%", $text)."%'";

    if($type === null && in_array($find, 'id', 'catid', 'modelid', 'listorder', 'status', 'hits')) {
      $sql = array();
      foreach(explode(',', $text) as $value) {
        if(is_numeric($value)) {
          array_push($sql, "`".$find."` = ".$value."");
        } else if(strstr($value, '-')) {
          $value = explode('-', $value);
          if(is_numeric($value[0]) && is_numeric($value[1]) && !isset($value[2])) array_push($sql, "`".$find."` between ".$value[0]." and ".$value[1]);
        }
      }
      return implode(" or ", $sql);
    };

    if($type === null && in_array($find, 'time', true) || in_array($type, array(), true));

    if($type === 'radio') {
      $sql = array();
      foreach(explode(',', $text) as $value) {
        if(is_numeric($value)) {
          array_push($sql, "`".$find."` = ".$value."");
        } else if (strstr($value, '-')) {
          $value = explode('-', $value);
          if(!isset($value[2])) {
            if(is_numeric($value[0]) && is_numeric($value[1])) {
              array_push($sql, "`".$find."` between ".$value[0]." and ".$value[1]);
            } else if(is_numeric($array[$value[0]] && is_numeric($array[$value[1]]))) {
              array_push($sql, "`".$find."` between ".$array[$value[0]]." and ".$array[$value[1]]);
            }
          }
        } else {
          $array = $this->getModelFieldSerialize($find);
          $getText = $this->getKeyInArray($text, $array, true);
          if(is_array($getText)) array_push($sql, "`".$find."` in (".implode(',', $getText).')');
        }
      }
      return implode(" or ", $sql);
    }

    if($type === 'checkbox') {
      $sql = array();
      foreach(explode(',', $text) as $value) {
        if(is_numeric($value)) {
          array_push($sql, "`".$find."` like '%".$value."%'");
        } else {
          $array = $this->getModelFieldSerialize($find);
          $getText = $this->getKeyInArray($value, $array, true);
          if(is_array($getText)) {
            foreach($getText as $t) {
              array_push($sql, "`".$find."` like '%:\"".$t."\";%'");
            }
          }
        }
      }
      return implode(" or ", $sql);
    }
  }

  protected function fieldToFormtype($field) {
    $formtype = $this->query("select formtype from ".$this->_prefix."model_field where field='".$field."';")->fetchAll(PDO::FETCH_ASSOC);
    return $formtype[0]['formtype'];
  }

  protected function getTableColumn($table) {
    $column = $this->query("select COLUMN_NAME from information_schema.COLUMNS where table_name = '".$table."';")->fetchAll(PDO::FETCH_ASSOC);
    $result = array();
    foreach($column as $value) array_push($result, $value['COLUMN_NAME']);
    return $result;
  }

  protected function getModelFieldSerialize($find) {
    $modelArray = $this->query("select setting from ".$this->_prefix."model_field where field='".$find."';")->fetchAll(PDO::FETCH_ASSOC);
    $modelArray = explode(chr(13), unserialize($modelArray[0]['setting'])['content']);
    foreach($modelArray as $value) {
      $value = explode('|', trim($value));
      $modelField[$value[1]] = $value[0];
    }
    return $modelField;
  }

  protected function getKeyInArray($find, $array, $fuzzy = false) {
    if($fuzzy) {
      foreach($array as $key => $value) {
        if(strstr($value, $find)) {
          $result[] = $key;
        }
      }
      return $result;
    } else {
      return array(array_flip($array)[$find]);
    }
  }

  public function sqlForm($param) {
    if(!$param['modelid']) exit('Modelid is not exits!');
    $tableNameResult = $this->query("select tablename from ".$this->_prefix."model where modelid=".$param['modelid'].";")->fetchAll(PDO::FETCH_ASSOC);
    $tableName = $this->_prefix.$tableNameResult[0]['tablename'];

    $findResult = $this->query("select field from ".$this->_prefix."model_field where modelid=".$param['modelid'].";")->fetchAll(PDO::FETCH_ASSOC);
    $find = array();
    foreach($findResult as $value) { array_push($find, $value['field']); }

    $sql = "select * from ".$tableName." where 1=1";
    if($param['status']) {
      $sql .= " and status in (".$param['status'].")";
    } else {
      $sql .= " and status=1";
    }
    foreach($find as $value) {
      if($param[$value]) $sql .= " and ".$value." like '%".$param[$value]."%'";
    }
    if($param['order']){
      $sql .= " order by ".$param['order'];
      if($param['desc']) $sql .= " DESC";
    }
    if($param['num']) $sql .= " limit ".$param['num'];
    $sql .= ";";

    $data = $this->query($sql)->fetchAll(PDO::FETCH_ASSOC);
    return $data;
  }

  public function sqlField($param) {
    $sql = "select * from ".$this->_prefix."model_field where 1=1";
    if($param['modelid']) {
      if(strstr($param['modelid'], ',')) {
        $sql .= " and modelid in (".$param['modelid'].")";
      } else {
        $sql .= " and modelid=".$param['modelid'];
      }
    }
    if($param['field']) {
      if(strstr($param['field'], ',')) {
        $sql .= " and field in ('".str_replace(",", "','", $param['field'])."')";
      } else {
        $sql .= " and field='".$param['field']."'";
      }
    }
    if($param['isshow']) {
      if(in_array($param['isshow'], array(0, 1))) {
        $sql .= " and isshow=".$param['isshow'];
      }
    } else {
      $sql .= " and isshow=1";
    }
    if($param['formtype']) {
      if(strstr($param['formtype'], ',')) {
        $sql .= " and formtype in ('".str_replace(",", "','", $param['formtype'])."')";
      } else {
        $sql .= " and formtype='".$param['formtype']."'";
      }
    }
    if($param['disabled'] and in_array($param['disabled'], array(0, 1)))
      $sql .= " and disabled=".$param['disabled'];
    if($param['order']){
      $sql .= " order by ".$param['order'];
      if($param['desc']) $sql .= " DESC";
    }
    if($param['num']) $sql .= " limit ".$param['num'];
    $sql .= ";";

    $result = $this->query($sql)->fetchAll(PDO::FETCH_ASSOC);
    $data = array();
    foreach($result as $value) {
      $setting = unserialize($value['setting']);
      $arr = array();
      foreach($setting as $k=>$v) {
        if(strstr($v, PHP_EOL)) {
          $vTemp = explode(PHP_EOL, $v);
          $v = array();
          foreach($vTemp as $item) {
            $item = explode('|', $item);
            $v = array_merge($v, array($item[1] => $item[0]));
          }
        }
        $arr[$k] = $v;
      }
      // unset($value['fieldid'], $value['setting']);
      unset($value['fieldid'], $value['setting'], $value['listorder']);
      if($param['setting']) {
        if($param['setting'] != 'zero') $value = $arr;
      } else {
        $value = array_merge($value, $arr);
      }

      if($param['find']) {
        if(strstr($param['find'], ',')) {
          $arr = array();
          foreach(explode(',', $param['find']) as $v) {
            $arr[$v] = $value[$v];
          }
          array_push($data, $arr);
        } else {
          array_push($data, $value[$param['find']]);
        }
      } else {
        array_push($data, $value);
      }
    }
    if(!$param['list'] && !strstr($param['modelid'], ',')) {
      $arr = array();
      foreach($data as $value) {
        $arr = array_merge($arr, array($value['field'] => $value));
      }
      $data = array($param['modelid'] => $arr);
    }
    return $data;
  }
}

class inkPager extends Pager {
  public function url($param) {
    if(!$param) return false;
    $url = 'index.php?';
    foreach($param as $key=>$value) $url .= $key.'='.$value.'&';
    if($url) $this->_url = trim($url, '&');
    return $this;
  }

  protected function _processData() {
    $this->_url = trim(str_replace(array("\n", "\r"), '', $this->_url));
    $this->_totalPages = $this->_getTotalPage();
    $this->_page = $this->_getPageNum();
    $data = array();
    if(!$this->_totalPages) return $data;
    if($this->_total <= $this->_num) return $data;
    if(strstr($this->_url, 'page=')) {
      $this->_url = preg_replace('/page=\d+/i', 'page=[page]', $this->_url);
    } else {
      $this->_url .= sizeof(strstr($this->_url, '&')) ? '&page=[page]': '?page=[page]';
    }
    $data['total'] = $this->_total;
    $data['num'] = $this->_num;
    $data['totalpage'] = $this->_totalPages;
    $data['page'] = $this->_page;
    $data['url'] = $this->_url;
    if($this->_totalPages > 1){
      $data['prepage'] = array(
        array('text' => $this->firstPage, 'url' => str_replace('[page]', 1, $this->_url)),
        array('text' => $this->prePage, 'url' => str_replace('[page]', ($this->_page == 1 ? $this->_page : $this->_page - 1), $this->_url)),
      );
    }
    if( $this->_totalPages > 1) {
      $data['nextpage'] = array(
        array('text' => $this->nextPage, 'url' => str_replace('[page]', ($this->_page == $this->_totalPages ? $this->_page : $this->_page + 1), $this->_url)),
        array('text' => $this->lastPage, 'url' => str_replace('[page]', $this->_totalPages, $this->_url)),
      );
    }
    if($this->_totalPages > $this->_perCircle) {
      if ($this->_page + $this->_perCircle >= $this->_totalPages + $this->_center) {
        $list_start = $this->_totalPages - $this->_perCircle + 1;
        $list_end = $this->_totalPages;
      } else {
        $list_start = ($this->_page > $this->_center) ? $this->_page - $this->_center + 1 : 1;
        $list_end = ($this->_page > $this->_center) ? $this->_page + $this->_perCircle - $this->_center : $this->_perCircle;
      }
    } else {
      $list_start = 1;
      $list_end = $this->_totalPages;
    }
    for($i = $list_start; $i <= $list_end; $i++) {
      if ($i == $this->_page) {
        $data['listpage'][] = array('text' => $i, 'current' => true);
      } else {
        $data['listpage'][] = array('text' => $i, 'current' => false, 'url' => str_replace('[page]', $i, $this->_url));
      }
    }
    return $data;
  }
}